package br.com.iswe.gerador.velocity.gerador;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import br.com.iswe.gerador.velocity.info.InfoEntidadeImpl;
import br.com.iswe.gerador.velocity.info.InfoGerador;

public class GeradorDAO extends GeradorBase {

	private static final String GERADOR_DAO_PASTA_SAIDA = "gerador.dao.pasta.saida";

	private static final String DAO_HIBERNATE_TEMPLATE_VM = "DAO-IMPL-TEMPLATE.vm";

	private static final String DAO_INTERFACE_TEMPLATE_VM = "DAO-INTERFACE-TEMPLATE.vm";
	
	private static final String DAO_ABSTRACT_TEMPLATE_VM = "DAO-ABSTRACT-TEMPLATE.vm";

	private static final String DAO_HIBERNATE_JAVA = "DAOImpl.java";

	private static final String DAO_JAVA = "DAO.java";
	private static final String DAO_ABSTRACT_JAVA = "DAOAbstract.java";

	private static final String PACOTE_DAO = "PacoteDAO";

	public static final String GERADOR_DAO_PACKAGE_TO = "gerador.dao.package.to";

	public static final String GERADOR_DAO_PACKAGE_FROM = "gerador.dao.package.from";

	public static final String NOME_GERADOR = "geradorDAO";

	private InfoGerador infoGerador;

	public void gerarCodigo(InfoEntidadeImpl info) throws Exception {
		Template template = null;
		Writer wrt = null;
		String arquivoSaida = null;
		
		//Obtem o pacote para objetos abstratos
        String pacoteAbstrato = infoGerador.getPacoteAbstratos();
		
		// Primeiro Passo : Cria o contexto com as informa��es necess�rias para
		// criar a classe de DAO.
		VelocityContext ctx = buildContext(this.infoGerador);
		// Obt�m o Pakage do componente :
		String packageDAO = info.getReplacePackage(GERADOR_DAO_PACKAGE_FROM, GERADOR_DAO_PACKAGE_TO);
		ctx.put(PACOTE_DAO, packageDAO);
		// Adiciona a info da entidade
		ctx.put(InfoEntidadeImpl.NOME_INFO, info);

		// Segundo Passo : Obt�m o diret�rio onde ser� gerado o fonte de sa�da.
		String basePath = infoGerador.getPastaBaseSaida() + SEPARADOR + infoGerador.getPropriedade(GERADOR_DAO_PASTA_SAIDA);
		File pathSaida = new File(basePath + SEPARADOR + infoGerador.getPathFromPackage(packageDAO));
		// Verifica se o path ja existe
		if (!pathSaida.exists()) {
			pathSaida.mkdirs();
		}
		
		//verifica se existe a pasta de abstratos
        File pastaAbstratos = new File(pathSaida.getAbsolutePath() + SEPARADOR + pacoteAbstrato);
        if(!pastaAbstratos.exists()){
            pastaAbstratos.mkdirs();
        }

		// Terceiro Passo : Verifica se a classe implementada do DAO j� est�
		// criada. Se estiver, aborta a gera��o da classe implementada
		arquivoSaida = pathSaida.getAbsolutePath() + SEPARADOR + info.getNomeEntidade1() + DAO_HIBERNATE_JAVA;
        if( infoGerador.shouldGenerateFile(arquivoSaida) ){
			// Quarto Passo : Obt�m o Template do DAO e gera a sa�da.
			// Gerando a classe de implementacao do DAO
			template = Velocity.getTemplate(DAO_HIBERNATE_TEMPLATE_VM);
			// Escreve o arquivo de sa�da
			wrt = new FileWriter(arquivoSaida);
			// Gera o documento.
			template.merge(ctx, wrt);
			// Descarrega para o disco.
			wrt.flush();
			wrt.close();
		}
        
        arquivoSaida = pathSaida.getAbsolutePath() + SEPARADOR + info.getNomeEntidade1() + DAO_JAVA;
        if( infoGerador.shouldGenerateFile(arquivoSaida) ){
			// Quarto Passo : Obt�m o Template do DAO e gera a sa�da.
			// Gerando a classe de implementacao do DAO
			template = Velocity.getTemplate(DAO_INTERFACE_TEMPLATE_VM);
			// Escreve o arquivo de sa�da
			wrt = new FileWriter(arquivoSaida);
			// Gera o documento.
			template.merge(ctx, wrt);
			// Descarrega para o disco.
			wrt.flush();
			wrt.close();
		}

		// Gerando a interface do DAO
		template = Velocity.getTemplate(DAO_ABSTRACT_TEMPLATE_VM);
		// Escreve o arquivo de sa�da
		wrt = new FileWriter(pastaAbstratos.getAbsolutePath() + SEPARADOR + info.getNomeEntidade1() + DAO_ABSTRACT_JAVA);
		// Gera o documento.
		template.merge(ctx, wrt);
		// Descarrega para o disco.
		wrt.flush();
		wrt.close();
	}

	public void inicio(InfoGerador infoGerador) {
		this.infoGerador = infoGerador;
	}

	public void fim() {
		this.infoGerador = null;
	}
}
